package com.epam.cdp.selenium2.core.common.test_data.files_utils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;

import com.epam.cdp.selenium2.core.results.logger.Logger;

/**
 * @author yyudzitski
 */
public class FilesUtils
{
  /**
   * Service method for getting name in temporary
   * 
   * @param fileName
   * @return
   */
  public String getTemporaryFileName( String fileName )
  {
    if( System.getProperty( "java.io.tmpdir" ).endsWith( File.separator ) )
    {
      return System.getProperty( "java.io.tmpdir" ) + fileName;
    }
    else
    {
      return System.getProperty( "java.io.tmpdir" ) + File.separator + fileName;
    }
  }

  /**
   * Service method for getting temporary directory name
   * 
   * @return
   */
  public String getTemporaryDirectory()
  {
    if( System.getProperty( "java.io.tmpdir" ).endsWith( File.separator ) )
    {
      return System.getProperty( "java.io.tmpdir" );
    }
    else
    {
      return System.getProperty( "java.io.tmpdir" ) + File.separator;
    }
  }

  /**
   * Service method for getting file size
   * 
   * @param fileName file full name
   * @return file size
   */
  public long getFileSize( String fileName )
  {
    File file = new File( fileName );
    return file.length();
  }

  /**
   * Write local text file
   * 
   * @param text
   */
  public File writeTextToFile( String fileName, String text )
  {
    Logger.operation( "Write text '" + text + "' to file " + fileName + "'" );
    File file = new File( fileName );
    try
    {
      BufferedWriter out = new BufferedWriter( new FileWriter( file ) );
      out.write( text );
      out.close();
    }
    catch( IOException ioe )
    {
      throw new RuntimeException( ioe );
    }
    return file;
  }

  /**
   * Gets test resource input stream. Test resources must be situated in 'resources/files'.
   * 
   * @param name file name
   * @return input stream
   */
  public InputStream getTestResource( String name )
  {
    return Thread.currentThread().getContextClassLoader().getResourceAsStream( "files/" + name );
  }

  /**
   * Extract file test resource and return full file name to local file
   * 
   * @param name file name
   * @return absolute path to file
   */
  public String getTestResourceAsFilePath( String name )
  {
    Logger.operation( "Return value of test resource '" + name + "' as file path" );
    try
    {
      File file = new File( new File( name ).getName() );
      FileOutputStream fos = new FileOutputStream( file );

      copyStream( getTestResource( name ), fos );
      fos.close();

      return file.getAbsolutePath();
    }
    catch( Exception e )
    {
      throw new RuntimeException( e );
    }
  }

  public String getTestResourceAsText( String name )
  {
    Logger.operation( "Return value of test resource '" + name + "' as text" );
    StringBuffer fileData = new StringBuffer( 1000 );
    BufferedReader reader = new BufferedReader( new InputStreamReader( getTestResource( name ) ) );
    char[] buf = new char[1024];
    int numRead = 0;
    try
    {
      while( ( numRead = reader.read( buf ) ) != -1 )
      {
        String readData = String.valueOf( buf, 0, numRead );
        fileData.append( readData );
        buf = new char[1024];
      }
      reader.close();
    }
    catch( IOException e )
    {
      throw new RuntimeException( "Cannot read resource " + name, e );
    }
    return fileData.toString();
  }

  /**
   * Create temp file with necessary name and size.
   * 
   * @param fileName
   * @param fileSize (in KBytes!)
   * @return File
   */
  public File createFileForUpload( String fileName, int fileSize )
  {
    Logger.operation( "Create temp file with necessary name and size of '" + fileSize + "'" );
    File fileForUpload = new File( getTemporaryFileName( fileName ) );
    try
    {
      RandomAccessFile f = new RandomAccessFile( fileForUpload, "rw" );
      f.setLength( 1024 * fileSize );
      f.close();
    }
    catch( IOException e )
    {
      throw new RuntimeException( e );
    }
    return fileForUpload;
  }

  public static void copyFileLocal( String src, String dst )
  {
    copyFileLocal( new File( src ), new File( dst ) );
  }

  public static void copyFileLocal( File in, File out )
  {
    try
    {
      InputStream fis = new FileInputStream( in );
      OutputStream fos = new FileOutputStream( out );
      copyStream( fis, fos );
    }
    catch( Exception ex )
    {
      throw new RuntimeException( ex );
    }
  }

  public static void copyStream( InputStream fis, OutputStream fos )
  {
    try
    {
      byte[] buf = new byte[1024];
      int i;
      while( ( i = fis.read( buf ) ) != -1 )
      {
        fos.write( buf, 0, i );
      }
      fis.close();
      fos.close();
    }
    catch( Exception e )
    {
      throw new RuntimeException( e );
    }
  }
}